#pragma once
#include <math.h>
#include <stdint.h>
#include <stddef.h>
#include "os.h"

typedef struct NODE
{
	struct NODE *prev;
	struct NODE *next;
} NODE;

typedef struct
{
	NODE     node;
	uint32_t size;
} LIST;


void INIT_LIST(LIST *list);

void list_add(NODE *new_node, NODE *head_node);

void list_del(NODE *node);


// 结构体指针 = 成员指针 - 成员偏移量
#define list_entry(member_ptr, type, member)    (type*)((char*)member_ptr - offsetof(type, member))

#define list_for_each_entry(pos, head, member, pos_type)\
	for (pos = list_entry((head)->next, pos_type, member);\
		 &pos->member != (head);\
		 pos = list_entry(pos->member.next, pos_type, member)\
	)

#define list_for_each_entry_start(pos, head, member, pos_type)  (pos = list_entry((head)->next, pos_type, member))
#define list_for_each_entry_end(  pos, head, member, pos_type)  (&pos->member != (head))
#define list_for_each_entry_next( pos, head, member, pos_type)  (pos = list_entry(pos->member.next, pos_type, member))

#define list_for_each_entry_safe(pos, tmp, head, member, pos_type)\
	for (pos = list_entry((head)->next, pos_type, member), tmp = list_entry(pos->member.next, pos_type, member);\
		 &pos->member != (head);\
		 pos = tmp, tmp = list_entry(tmp->member.next, pos_type, member)\
	)


#define LIST_INIT(type)\
	void type##_LIST_init(LIST *list) {\
		if(!list) return;\
		INIT_LIST(list);\
	}

#define LIST_FREE(type, node)\
	void type##_LIST_free(LIST *list) {\
		type *elem, *tmp;\
		\
		if(!list) return;\
		\
		list_for_each_entry_safe(elem, tmp, &list->node, node, type) {\
			list_del(&elem->node);\
			list->size--;\
			type##_free(elem);\
		}\
	}

#define LIST_ADD(type, node)\
	void type##_LIST_add(LIST *list, type *elem) {\
		if(!list || !elem) return;\
		list_add(&elem->node, &list->node);\
		list->size++;\
	}

#define LIST_GET(type, node)\
	type* type##_LIST_get(LIST *list, int idx) {\
		type *elem;\
		int cnt;\
		\
		if(!list) return NULL;\
		cnt = 0;\
		list_for_each_entry(elem, &list->node, node, type) {\
			if(cnt == idx) return elem;\
			cnt++;\
		}\
		return NULL;\
	}


#define LIST_XXXX(type, node)\
		LIST_INIT(type      )\
		LIST_FREE(type, node)\
		LIST_ADD (type, node)\
		LIST_GET (type, node)
